import pygame
import random
import sys

# 初始化pygame
pygame.init()

# 游戏设置
CELL_SIZE = 30
GRID_WIDTH = 10
GRID_HEIGHT = 10
MINES_COUNT = 10
WINDOW_WIDTH = GRID_WIDTH * CELL_SIZE
WINDOW_HEIGHT = GRID_HEIGHT * CELL_SIZE + 50  # 额外空间用于显示信息
INFO_HEIGHT = 50

# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GRAY = (192, 192, 192)
DARK_GRAY = (128, 128, 128)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
GREEN = (0, 128, 0)
PURPLE = (128, 0, 128)
MAROON = (128, 0, 0)
TURQUOISE = (0, 128, 128)
DARK_BLUE = (0, 0, 128)
ORANGE = (255, 165, 0)

# 数字颜色
NUMBER_COLORS = {
    1: BLUE,
    2: GREEN,
    3: RED,
    4: PURPLE,
    5: MAROON,
    6: TURQUOISE,
    7: BLACK,
    8: DARK_GRAY
}

# 创建窗口
screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
pygame.display.set_caption("扫雷游戏")
clock = pygame.time.Clock()

# 字体
font = pygame.font.SysFont(None, 24)
large_font = pygame.font.SysFont(None, 36)

class Cell:
    def __init__(self):
        self.is_mine = False
        self.is_revealed = False
        self.is_flagged = False
        self.adjacent_mines = 0

class Minesweeper:
    def __init__(self, width, height, mines):
        self.width = width
        self.height = height
        self.mines_count = mines
        self.grid = [[Cell() for _ in range(width)] for _ in range(height)]
        self.game_over = False
        self.game_won = False
        self.first_click = True
        
        self.place_mines()
        self.calculate_adjacent_mines()
    
    def place_mines(self):
        # 放置地雷
        mines_placed = 0
        while mines_placed < self.mines_count:
            x = random.randint(0, self.width - 1)
            y = random.randint(0, self.height - 1)
            if not self.grid[y][x].is_mine:
                self.grid[y][x].is_mine = True
                mines_placed += 1
    
    def calculate_adjacent_mines(self):
        # 计算每个格子周围的地雷数
        for y in range(self.height):
            for x in range(self.width):
                if not self.grid[y][x].is_mine:
                    count = 0
                    for dy in [-1, 0, 1]:
                        for dx in [-1, 0, 1]:
                            ny, nx = y + dy, x + dx
                            if 0 <= ny < self.height and 0 <= nx < self.width:
                                if self.grid[ny][nx].is_mine:
                                    count += 1
                    self.grid[y][x].adjacent_mines = count
    
    def reveal(self, x, y):
        # 揭开格子
        if not (0 <= x < self.width and 0 <= y < self.height):
            return
        
        cell = self.grid[y][x]
        
        if cell.is_revealed or cell.is_flagged:
            return
        
        # 第一次点击确保不是地雷
        if self.first_click:
            self.first_click = False
            if cell.is_mine:
                # 移除这个地雷并放置到其他地方
                cell.is_mine = False
                while True:
                    nx = random.randint(0, self.width - 1)
                    ny = random.randint(0, self.height - 1)
                    if not self.grid[ny][nx].is_mine and (nx, ny) != (x, y):
                        self.grid[ny][nx].is_mine = True
                        break
                self.calculate_adjacent_mines()
        
        cell.is_revealed = True
        
        if cell.is_mine:
            self.game_over = True
            return
        
        # 如果周围没有地雷，则自动揭开周围的格子
        if cell.adjacent_mines == 0:
            for dy in [-1, 0, 1]:
                for dx in [-1, 0, 1]:
                    self.reveal(x + dx, y + dy)
        
        # 检查是否获胜
        self.check_win()
    
    def toggle_flag(self, x, y):
        # 标记/取消标记地雷
        if not (0 <= x < self.width and 0 <= y < self.height):
            return
        
        cell = self.grid[y][x]
        
        if not cell.is_revealed:
            cell.is_flagged = not cell.is_flagged
    
    def check_win(self):
        # 检查是否获胜
        for y in range(self.height):
            for x in range(self.width):
                cell = self.grid[y][x]
                if not cell.is_mine and not cell.is_revealed:
                    return
        
        self.game_won = True
    
    def reveal_all_mines(self):
        # 显示所有地雷
        for y in range(self.height):
            for x in range(self.width):
                if self.grid[y][x].is_mine:
                    self.grid[y][x].is_revealed = True

def draw_game(game):
    # 绘制游戏界面
    screen.fill(WHITE)
    
    # 绘制网格
    for y in range(game.height):
        for x in range(game.width):
            cell = game.grid[y][x]
            rect = pygame.Rect(x * CELL_SIZE, y * CELL_SIZE + INFO_HEIGHT, CELL_SIZE, CELL_SIZE)
            
            if cell.is_revealed:
                pygame.draw.rect(screen, GRAY, rect)
                pygame.draw.rect(screen, DARK_GRAY, rect, 1)
                
                if cell.is_mine:
                    # 绘制地雷
                    pygame.draw.circle(screen, BLACK, rect.center, CELL_SIZE // 3)
                    # 绘制地雷的十字交叉线
                    pygame.draw.line(screen, BLACK, 
                                   (rect.centerx - 5, rect.centery), 
                                   (rect.centerx + 5, rect.centery), 2)
                    pygame.draw.line(screen, BLACK, 
                                   (rect.centerx, rect.centery - 5), 
                                   (rect.centerx, rect.centery + 5), 2)
                elif cell.adjacent_mines > 0:
                    # 绘制数字
                    text = font.render(str(cell.adjacent_mines), True, NUMBER_COLORS[cell.adjacent_mines])
                    text_rect = text.get_rect(center=rect.center)
                    screen.blit(text, text_rect)
            else:
                # 未揭开的格子
                pygame.draw.rect(screen, DARK_GRAY, rect)
                pygame.draw.rect(screen, WHITE, rect, 2)
                
                if cell.is_flagged:
                    # 绘制旗帜
                    pygame.draw.polygon(screen, RED, [
                        (rect.left + 5, rect.top + 5),
                        (rect.left + 5, rect.bottom - 5),
                        (rect.right - 5, rect.centery)
                    ])
            
            # 绘制网格线
            pygame.draw.rect(screen, BLACK, rect, 1)
    
    # 绘制信息区域
    info_rect = pygame.Rect(0, 0, WINDOW_WIDTH, INFO_HEIGHT)
    pygame.draw.rect(screen, DARK_GRAY, info_rect)
    
    # 显示剩余地雷数
    flags_count = sum(1 for row in game.grid for cell in row if cell.is_flagged)
    mines_left = game.mines_count - flags_count
    mines_text = font.render(f"剩余地雷: {mines_left}", True, WHITE)
    screen.blit(mines_text, (10, 15))
    
    # 显示游戏状态
    if game.game_over:
        status_text = large_font.render("游戏结束! 按R重新开始", True, RED)
        text_rect = status_text.get_rect(center=(WINDOW_WIDTH // 2, INFO_HEIGHT // 2))
        screen.blit(status_text, text_rect)
    elif game.game_won:
        status_text = large_font.render("恭喜获胜! 按R重新开始", True, GREEN)
        text_rect = status_text.get_rect(center=(WINDOW_WIDTH // 2, INFO_HEIGHT // 2))
        screen.blit(status_text, text_rect)

def main():
    game = Minesweeper(GRID_WIDTH, GRID_HEIGHT, MINES_COUNT)
    
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    running = False
                elif event.key == pygame.K_r:
                    # 重新开始游戏
                    game = Minesweeper(GRID_WIDTH, GRID_HEIGHT, MINES_COUNT)
            
            elif event.type == pygame.MOUSEBUTTONDOWN and not game.game_over and not game.game_won:
                x, y = event.pos
                grid_x = x // CELL_SIZE
                grid_y = (y - INFO_HEIGHT) // CELL_SIZE
                
                if 0 <= grid_x < GRID_WIDTH and 0 <= grid_y < GRID_HEIGHT:
                    if event.button == 1:  # 左键
                        game.reveal(grid_x, grid_y)
                    elif event.button == 3:  # 右键
                        game.toggle_flag(grid_x, grid_y)
        
        # 如果游戏结束，显示所有地雷
        if game.game_over:
            game.reveal_all_mines()
        
        draw_game(game)
        pygame.display.flip()
        clock.tick(60)
    
    pygame.quit()
    sys.exit()

if __name__ == "__main__":
    main()